package solverStrategies;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import junit.framework.Assert;

import org.junit.Test;

public class HiddenSubset {

	static Set<Integer> s1 = new HashSet<Integer>();
	static Set<Integer> s2 = new HashSet<Integer>();
	static Set<Integer> s3 = new HashSet<Integer>();
	static Set<Integer> s4 = new HashSet<Integer>();
	static Set<Integer> s5 = new HashSet<Integer>();
	static Set<Integer> s6 = new HashSet<Integer>();
	static Set<Integer> s7 = new HashSet<Integer>();
	static List<Set<Integer>> allSets = new ArrayList<Set<Integer>>();

	static Map<Set<Integer>, Integer> setCounter = new HashMap<Set<Integer>, Integer>();

	@Test
	public void init() {
		/*
		 * s1 = 1,3,4 | s2 = 3,4,5 | s3 = 6,7 | s4 = 6,7 | s5 = 5,8,9 s6 = 8,9 s7 = 8,9
		 * 
		 * Zu finden: 3,4 und 6,7 und 8,9
		 */
		s1.add(1);
		s1.add(3);
		s1.add(4);
		
		s2.add(3);
		s2.add(4);
		s2.add(5);
		
		s3.add(6);
		s3.add(7);
		
		s4.add(1);
		s4.add(6);
		s4.add(7);
		
		s5.add(5);
		s5.add(8);
		s5.add(9);
		
		s6.add(8);
		s6.add(9);
		
		s7.add(8);
		s7.add(9);

		allSets.add(s1);
		allSets.add(s2);
		allSets.add(s3);
		allSets.add(s4);
		allSets.add(s5);
		allSets.add(s6);
		allSets.add(s7);

		/*
		 * Bilde aus jedem Set Teilmengen und schaue wie oft diese vorkommen.
		 */
		buildSubsets();
	}

	private void buildSubsets() {
		/*
		 * 1,2,6,7 = (), (1),(2),(6),(7), (1,2), (1,6), (1,7), (2,6), (2,7), (6,7), (1,2,6), (1,2,7),
		 * (1,6,7), (2,6,7), (1,2,6,7) = 16
		 */
		for (Set<Integer> singleSe : allSets) {
			Set<Set<Integer>> tmp = buildSubSetsFromOneSet(singleSe,3);
			for (Set<Integer> set : tmp) {
//				System.out.println(set);
				insert(set);
			}
//			Assert.assertEquals(16, tmp.size());
		}
		
		
		printMap();
	}
	
	private void printMap() {
		Set<Set<Integer>> bla = setCounter.keySet();
		List<Set<Integer>> blaList = new ArrayList<Set<Integer>>(bla);
		Comparator<Set<Integer>> setComparator = new Comparator<Set<Integer>>() {

			@Override
			public int compare(Set<Integer> arg0, Set<Integer> arg1) {
				return arg0.size()-arg1.size();
			}
		};
		Collections.sort(blaList, setComparator);
		for (Set<Integer> set : blaList) {
			int counter = setCounter.get(set);
//			if(counter == set.size()){
				System.out.println(counter + " * " + set);
//			}
		}
	}

	private void insert(Set<Integer> set){
		if(setCounter.containsKey(set)){
			int counter = setCounter.get(set);
			setCounter.put(set, counter+1);
		}else {
			setCounter.put(set, 1);
		}
	}

	private Set<Set<Integer>> buildSubSetsFromOneSet(Set<Integer> singleSet, int size) {
		Set<Set<Integer>> singlesubsets = new HashSet<Set<Integer>>();
		if(singleSet.size() == size || singleSet.isEmpty()){
			singlesubsets.add(new HashSet<Integer>());
			return singlesubsets;
		}
		List<Integer> tmp = new ArrayList<Integer>(singleSet);
		Integer head = tmp.get(0);
		Set<Integer> rest = new HashSet<Integer>(tmp.subList(1, tmp.size()));
		for (Set<Integer> set:buildSubSetsFromOneSet(rest, size)) {
			Set<Integer> newSet = new HashSet<Integer>();
			newSet.add(head);
			newSet.addAll(set);
			singlesubsets.add(newSet);
			singlesubsets.add(set);
		}
		return singlesubsets;
	}

}
